package com.relax;

import org.assertj.core.util.Lists;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

/**
 * @author kunlun.tian
 * @since 2019-11-27 14:33 
 */
@Component
public class SpringTestFactoryBeanPostProcessor implements BeanFactoryPostProcessor {
   // 要屏蔽的class
    private static  Set<String> EXCLUDE_BEAN_CLASSES =new HashSet<>();

    // 要屏蔽的含有某些注解的bean
    private static final Set<String> ANNOTATION_BEAN_CLASSES = new HashSet<>();

    static {
        EXCLUDE_BEAN_CLASSES.add("com.ooo.finance.vehicle.disposal.core.job.config.OpjobManagerConfig");
        EXCLUDE_BEAN_CLASSES.add("com.alibaba.dubbo.config.spring.ServiceBean");
        EXCLUDE_BEAN_CLASSES.add( "com.ooo.optimus.mq.aliyunons.ONSConsumerInvoker");

        ANNOTATION_BEAN_CLASSES.add("com.xxx.opjobclient.annotation.JobHandler");
    }
   //


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        DefaultListableBeanFactory defaultBeanFactory = (DefaultListableBeanFactory) beanFactory;
        // 通过beanFactory获取所有BeanDefinition名称
        ArrayList<String> definitionNames = Lists.newArrayList(defaultBeanFactory.getBeanDefinitionNames());
        // 遍历所有definitionName
        for (String definitionName : definitionNames) {
            // 通过DefaultListableBeanFactory中的beanDefinitionMap获取definitionName对应的BeanDefinition
            BeanDefinition beanDefinition = defaultBeanFactory.getBeanDefinition(definitionName);
            String beanClassName = beanDefinition.getBeanClassName();
            
            if (EXCLUDE_BEAN_CLASSES.contains(beanClassName)) {
                //排除掉beanDefinition，即从维护的beanDefinitionMap和beanDefinitionNames中删除掉对应的beanDefintion和beanDefintionName。
                defaultBeanFactory.removeBeanDefinition(definitionName);
            }
            if (beanDefinition instanceof ScannedGenericBeanDefinition) {
                ScannedGenericBeanDefinition sgbd = (ScannedGenericBeanDefinition) beanDefinition;
                AnnotationMetadata metadata = sgbd.getMetadata();
                for (String annotationBeanClass : ANNOTATION_BEAN_CLASSES) {
                     //判断是否含有某些注解
                    if(metadata.hasAnnotation(annotationBeanClass)){
                     // 排除含有注解的beanDefinition
                     defaultBeanFactory.removeBeanDefinition(definitionName);
                    }
                }
            }
            
            // OpjobManagerConfig可以理解成一个配置类，其通过@Bean注解引入OpjobManager，所以将其排除。
            if ("opjobManagerConfig".equals(beanDefinition.getFactoryBeanName())) {
                defaultBeanFactory.removeBeanDefinition(definitionName);
            }
            
            // 替换ONSProducer对应的beanDefinition的class，这样也不会真正地去发消息了。
//            if (ONSProducer.class.getName().equals(beanDefinition.getBeanClassName())) {
//                beanDefinition.setBeanClassName(MockOnsProducer.class.getName());
//            }
        }
    }
}
